﻿using System;
using System.Threading;
using Cysharp.Threading.Tasks;
using DG.Tweening;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Logic;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class StoryAction_Fade : StoryAction
    {
        private EStoryActionInOut type;
        private float alpha;
        private float duration;

        private CanvasGroup _canvasGroup;

        protected override bool OnInitialize(GameObject root, StoryActionData data)
        {
            base.OnInitialize(root, data);
            if (data is StoryActionData_Fade rFade)
            {
                this.type = rFade.type;
                this.alpha = rFade.alpha;
                this.duration = rFade.duration;
                return true;
            }
            return false;
        }

        protected override void OnBeforeStart()
        {
            base.OnBeforeStart();
            if (this.type == EStoryActionInOut.Out)
            {
                return;
            }
            this.SetAlpha(this.alpha);
        }

        protected override async UniTask OnStart(CancellationToken cancel)
        {
            await base.OnStart(cancel);
            if (this.type == EStoryActionInOut.Out)
            {
                return;
            }
            var fStart = this.alpha;
            var fTarget = 1;
            this.SetAlpha(fStart);
            var rTween = DOTween.To(this.GetAlpha, this.SetAlpha, fTarget, this.duration);
            await rTween.PlayAsync(cancel);
        }

        protected override void OnBeforeEnd()
        {
            base.OnBeforeEnd();
            if (this.type == EStoryActionInOut.In)
            {
                return;
            }
            this.SetAlpha(1);
        }

        protected override async UniTask OnEnd(CancellationToken cancel)
        {
            await base.OnEnd(cancel);
            if (this.type == EStoryActionInOut.In)
            {
                return;
            }
            var fStart = 1;
            var fTarget = this.alpha;
            this.SetAlpha(fStart);
            var rTween = DOTween.To(this.GetAlpha,
                this.SetAlpha, 
                fTarget, this.duration);
            await rTween.PlayAsync(cancel);
        }

        private float GetAlpha()
        {
            try
            {
                // 如果没有赋值getter和setter，就用默认的
                var rGetter = this.GetDynamic<Func<float>>(EStoryActionDynamicKey.AlphaGetter);
                if (rGetter == default)
                {
                    if (!this._canvasGroup)
                    {
                        this._canvasGroup = root.GetComponent<CanvasGroup>();
                    }
                    if (this._canvasGroup)
                    {
                        return this._canvasGroup.alpha;
                    }
                }
                return rGetter?.Invoke() ?? 0f;
            }
            catch
            {
                return 0f;
            }
        }

        private void SetAlpha(float value)
        {
            try
            {
                // 如果没有赋值getter和setter，就用默认的
                var rSetter = this.GetDynamic<Action<float>>(EStoryActionDynamicKey.AlphaSetter);
                if (rSetter == default)
                {
                    if (!this._canvasGroup)
                    {
                        this._canvasGroup = root.GetComponent<CanvasGroup>();
                    }
                    if (this._canvasGroup)
                    {
                        this._canvasGroup.alpha = value;
                    }
                }
                rSetter?.Invoke(value);
            }
            catch
            {
                // ignored
            }
        }

        public override void OnReset()
        {
            base.OnReset();
            this.type = default;
            this.alpha = default;
            this.duration = default;
            this._canvasGroup = default;
        }

        public override void Free()
        {
            ClassPool.Put(this);
        }
    }
}